/**
 * http://auzll.iteye.com/
 */
package z.action;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import z.tool.util.ZUtils;

import com.google.inject.internal.Lists;

/**
 * @author http://weibo.com/zhengll
 * @since 2011-3-10
 */
public final class Context {
    private static final ThreadLocal<Context> ACTION_CONTEXT = new ThreadLocal<Context>();

    private static final Log LOG = LogFactory.getLog(Context.class);

    public static Context getActionContext() {
        return ACTION_CONTEXT.get();
    }

    public static Context removeActionContext() {
        Context context = getActionContext();
        if (null != context) {
            ACTION_CONTEXT.remove();
        }
        return context;
    }

    public static Context setActionContext(HttpServletRequest request,
            HttpServletResponse response) {
        ACTION_CONTEXT.set(new Context(request, response));
        return getActionContext();
    }

    private SimpleDateFormat detailFormat;

    private SimpleDateFormat normalFormat;

    private HttpServletRequest request;

    private HttpServletResponse response;

    private SimpleDateFormat simpleFormat;

    private Context(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public boolean getRequestBoolean(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return false;
        }
        try {
            return Boolean.valueOf(string);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * parseDate: yyyy-MM-dd HH:mm:ss, yyyy-MM-dd HH:mm, yyyy-MM-dd
     */
    public Date getRequestDate(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return null;
        }
        Date date = null;
        try {
            date = getDetailFormat().parse(string);
        } catch (ParseException d) {
            try {
                date = getNormalFormat().parse(string);
            } catch (Exception n) {
                try {
                    date = getSimpleFormat().parse(string);
                } catch (Exception s) {}
            }
        }
        return date;
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public SimpleDateFormat getDetailFormat() {
        if (null == detailFormat) {
            detailFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
        return detailFormat;
    }

    public Double getRequestDouble(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return null;
        }
        try {
            return Double.parseDouble(string);
        } catch (Exception e) {
            return null;
        }
    }

    public Double getRequestDouble(String argName, Double defaultValue) {
        Double value = getRequestDouble(argName);
        return null == value ? defaultValue : value;
    }

    public Float getRequestFloat(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return null;
        }
        try {
            return Float.parseFloat(string);
        } catch (Exception e) {
            return null;
        }
    }

    public Float getRequestFloat(String argName, Float defaultValue) {
        Float value = getRequestFloat(argName);
        return null == value ? defaultValue : value;
    }

    public Integer getRequestInteger(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return null;
        }
        try {
            return Integer.parseInt(string);
        } catch (Exception e) {
            return null;
        }
    }

    public Integer getRequestInteger(String argName, Integer defaultValue) {
        Integer value = getRequestInteger(argName);
        return null == value ? defaultValue : value;
    }

    public List<Integer> getRequestIntegerList(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return Collections.emptyList();
        }
        String[] values = string.split(",");
        List<Integer> list = Lists.newArrayList();
        for (String value: values) {
            try {
                list.add(Integer.parseInt(value));
            } catch (Exception e) {}
        }
        return list;
    }

    public Long getRequestLong(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return null;
        }
        try {
            return Long.parseLong(string);
        } catch (Exception e) {
            return null;
        }
    }

    public Long getRequestLong(String argName, Long defaultValue) {
        Long value = getRequestLong(argName);
        return null == value ? defaultValue : value;
    }

    public List<Long> getRequestLongList(String argName) {
        String string = preGetValue(argName, true);
        if (null == string) {
            return Collections.emptyList();
        }
        String[] values = string.split(",");
        List<Long> list = Lists.newArrayList();
        for (String value: values) {
            try {
                list.add(Long.parseLong(value));
            } catch (Exception e) {}
        }
        return list;
    }

    /**
     * yyyy-MM-dd HH:mm
     */
    public SimpleDateFormat getNormalFormat() {
        if (null == normalFormat) {
            normalFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        }
        return normalFormat;
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public String getRequestIp() {
        if (null == request) {
            return null;
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ZUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            if (ZUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
                if (ZUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                }
            }
        }
        int idx = -1;
        if (!ZUtils.isEmpty(ip) && (idx = ip.indexOf(',')) > -1) {
            ip = ip.substring(0, idx);
        }
        return ip;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public HttpSession getSession() {
        return null == getRequest() ? null : getRequest().getSession();
    }

    /**
     * yyyy-MM-dd
     */
    public SimpleDateFormat getSimpleFormat() {
        if (null == simpleFormat) {
            simpleFormat = new SimpleDateFormat("yyyy-MM-dd");
        }
        return simpleFormat;
    }

    public String getRequestString(String argName) {
        return preGetValue(argName, true);
    }

    public String getRequestString(String argName, String defaultValue) {
        String value = getRequestString(argName);
        return null == value ? defaultValue : value;
    }

    public String tryToGetApi() {
        String argName = "api";
        String value = preGetValue(argName, true);
        if (null == value) {
            value = preGetValue(argName, false);
        }
        if (null == value) {
            if (LOG.isDebugEnabled()) {
                // 对于文件上传的情况，可能由于contentType为multipart/form-data，无法直接从request中获取参数。
                // 可以把form的action设置为xxx.do?api=xxx，这样就能根据getRequest().getQueryString()分析到api
                LOG.debug("method:getStringDeeply,contentType:" + request.getContentType() + ",argName:" + argName);
            }
        }
        return value;
    }

    /**
     * 获取请求参数，不处理contentType为multipart/form-data的，需要自己的程序里面用
     * commons-fileupload来解释request，调用getRequest()即可获取到request
     */
    private String preGetValue(String argName, boolean typical) {
        if (null == getRequest() || null == argName) {
            return null;
        }

        String paramValue = null;
        if (typical) {
            paramValue = getRequest().getParameter(argName);
        } else {
            String queryString = ZUtils.trimStringNull(getRequest().getQueryString());
            if (null == queryString) {
                return null;
            }
            Pattern pattern = Pattern.compile("(\\?|&){0,1}" + argName + "=(.*?)&{0,1}");
            Matcher matcher = pattern.matcher(queryString);
            if (matcher.matches() && matcher.groupCount() >= 2) {
                paramValue = matcher.group(2);
            }
        }
        if (null == (paramValue = ZUtils.trimStringNull(paramValue))) {
            return null;
        }

        return paramValue;
    }

}
